﻿using System;
using System.Globalization;
using QAToolsAddin.GenericDialogs;
using QAToolsAddin.GenericDialogs.Fields;
using Excel = Microsoft.Office.Interop.Excel;

namespace QAToolsAddin.UI {
    class Num {
        private readonly Excel.Application _excelapp;
        private Excel.Range _range;
        private CultureInfo _culture;

        public Num(Excel.Application application, CultureInfo culture) {
            try {
                _excelapp = application;
                _culture = culture;
                _range = application.ActiveWindow.RangeSelection;
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }

        public void ToCustomText() {
            var f1 = new FieldText("Format", "Format to apply", "# ###.00", ".+", "Format is empty", true);
            new InputBox(_excelapp, "To text", f1).Show(delegate {
                var format = f1.Value;
                new CellsOperator(_range).ForEachValue("@", delegate(ref object value) {
                    object number;
                    if (Parser.Number(value, out number))
                        value = ((double)number).ToString(format, CultureInfo.InvariantCulture);
                });
            });
        }

        public void ToAbsolute() {
            try {
                new CellsOperator(_range).ForEachValue(null, delegate(ref object value) {
                    if (value is double)
                        value = Math.Abs((double)value);
                    if (value is decimal)
                        value = Math.Abs((decimal)value);
                });
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }

        public void Round() {
            var f0 = new FieldRadioBT("", new string[] { "Nearest", "Down", "Up" }, "", 0);
            var f1 = new FieldNumber("Precision", "Number of digit after the decimal point", 0, 0, 15);
            new InputBox(_excelapp, "Round", f0, f1).Show(delegate {
                int precision = (int)(f1.Value ?? 0);
                double raise = Math.Pow(10, precision);
                double down = Math.Pow(10, -1 * precision);
                if (f0.Value == 1) {
                    new CellsOperator(_range).ForEachValue(null, delegate(ref object value) {
                        if (value is double)
                            value = Math.Floor((double)value * raise) * down;
                        if (value is decimal)
                            value = Math.Floor((decimal)value * (decimal)raise) * (decimal)down;
                    });
                } if (f0.Value == 2) {
                    new CellsOperator(_range).ForEachValue(null, delegate(ref object value) {
                        if (value is double)
                            value = Math.Ceiling((double)value * raise) * down;
                        if (value is decimal)
                            value = Math.Ceiling((decimal)value * (decimal)raise) * (decimal)down;
                    });
                } else {
                    new CellsOperator(_range).ForEachValue(null, delegate(ref object value) {
                        if (value is double)
                            value = Math.Round((double)value, precision);
                        else if (value is decimal)
                            value = Math.Round((decimal)value, precision);
                    });
                }
            });
        }

        public void ToggleSign() {
            try {
                new CellsOperator(_range).ForEachValue(null, delegate(ref object value) {
                    if (value is double)
                        value = -(double)value;
                    if (value is decimal)
                        value = -(decimal)value;
                });
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }

        public void Add() {
            var f0 = new FieldNumber("Value", "Value", 0d);
            var f1 = new FieldRadioBT("Operation", new string[] { "Add", "Subtract" }, null, 0);
            new InputBox(_excelapp, "Add value", f0, f1).Show(delegate {
                bool add = f1.Value == 0;
                double val = f0.Value ?? 0;
                new CellsOperator(_range).ForEachValue(null, delegate(ref object value) {
                    if (value is double) {
                        if (add)
                            value = (double)value + val;
                        else
                            value = (double)value - val;
                    }
                });
            });
        }

        public void Multiply() {
            var f0 = new FieldNumber("Value", "Value", 0d);
            var f1 = new FieldRadioBT("Operation", new string[] { "Multiply", "Divide" }, null, 0);
            var f2 = new FieldNumber("Rounding", "Number of digit after the decimal point (empty=disabled)", (double?)null, 0);
            new InputBox(_excelapp, "Multiply / Divide", f0, f1, f2).Show(delegate {
                bool multiply = f1.Value == 0;
                double val = f0.Value ?? 0;
                int round = (int)(f2.Value ?? -1);
                new CellsOperator(_range).ForEachValue(null, delegate(ref object value) {
                    if (value is double) {
                        if (multiply)
                            value = (double)value * val;
                        else
                            value = (double)value / val;
                        if (round != -1)
                            value = Math.Round((double)value, round);
                    }
                });
            });
        }

        public void ReplaceIf() {
            var f1 = new FieldRadioBT("If value is", new string[] { "Inferior", "Superior" }, "Compare type", 0);
            var f2 = new FieldNumber("To", "Value to compare with", 0);
            var f3 = new FieldNumber("Replace with", "Replacement value", 0);
            new InputBox(_excelapp, "Replace if", f1, f2, f3).Show(delegate {
                double bound = f2.Value ?? 0;
                double replacement = f3.Value ?? 0;
                if (f1.Value == 1) {
                    new CellsOperator(_range).ForEachValue(null, delegate(ref object value) {
                        if (value is double && (double)value > bound)
                            value = replacement;
                        else if (value is decimal && (decimal)value > (decimal)bound)
                            value = replacement;
                    });
                } else {
                    new CellsOperator(_range).ForEachValue(null, delegate(ref object value) {
                        if (value is double && (double)value < bound)
                            value = replacement;
                        else if (value is decimal && (decimal)value < (decimal)bound)
                            value = replacement;
                    });
                }
            });
        }

    }
}
